package com.beiding.codecreater.core.render;

import org.springframework.cglib.beans.BeanMap;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.util.*;

//标准模板
public class Template {

    //模板的文本
    private String text;

    //所有的占位符
    private List<Render> values;

    private String errorText;

    //只解析最外层代码块
    //一块模板中可能蕴含着多个重复代码块
    private List<RepeatBlock> repeatBlocks;

    List<RepeatBlock> getRepeatBlocks() {
        return repeatBlocks;
    }


    List<Render> getValues() {
        return values;
    }

    static Template create(String text, List<URepeatBlock.Pair> pairs, URepeatBlock uRepeatBlock, URender uValue, String errorText) {

        Template template = new Template();

        template.errorText = errorText;

        //直接把文本处理成替换后的文本
        text = uRepeatBlock.replaceBlock(text, pairs);

        List<URender.Pair> parsePairs = uValue.parsePairs(text);

        text = uValue.replaceBlock(text, parsePairs);

        template.text = text;

        template.values = new ArrayList<>();
        for (URender.Pair pair : parsePairs) {
            Render value = new Render(pair.getHolder(), pair.getBody(), pair.getBlockStart().condition == null ? null : "__global." + pair.getBlockStart().condition);
            template.values.add(value);
        }

        template.repeatBlocks = new ArrayList<>();
        for (URepeatBlock.Pair pair : pairs) {

            //将所有层级为0的处理代码对
            if (pair.getHierarchy() == 0) {

                String repeat = pair.getBlockStart().getRepeat();

                String items = null;
                String item = null;

                if (repeat != null) {
                    String[] split = repeat.split(" in ");

                    if (split.length != 2) {
                        throw new RuntimeException("模板错误!不能识别的表达式:" + repeat);
                    }

                    items = "__global." + split[1];
                    item = split[0];

                }


                RepeatBlock repeatBlock = new RepeatBlock(pair.getHolder(), Template.create(pair.getBody(), pair.getToRootInners(), uRepeatBlock, uValue, errorText), items, item, pair.getBlockStart().getCondition() == null ? null : "__global." + pair.getBlockStart().getCondition());
                template.repeatBlocks.add(repeatBlock);
            }
        }
        return template;
    }

    @Override
    public String toString() {
        return text;
    }

    private static ScriptEngineManager manager = new ScriptEngineManager();

    //开始执行渲染操作
    public String render(Object data) {

        if (!(data instanceof Map)) {
            data = BeanMap.create(data);
        }

        Map allData = (Map) data;

        ScriptEngine engine = manager.getEngineByName("Nashorn");

        engine.put("__global", allData);

        String r = text;

        for (Render value : values) {


            boolean error = false;
            boolean condition = true;

            try {
                if (value.getCondition() != null && !(boolean) engine.eval("!!" + value.getCondition())) {
                    condition = false;
                }
            } catch (Exception e) {
                e.printStackTrace();
                error = true;
            }

            if (error) {
                r = r.replace(value.getHolder(), errorText);
            } else if (condition) {
                Object res = null;
                try {
                    res = engine.eval(value.getExpression());
                } catch (Exception e) {
                    e.printStackTrace();
                    error = true;
                }
                if (error) {
                    r = r.replace(value.getHolder(), errorText);
                } else {
                    if (res == null) {
                        r = r.replace(repString(r, value.getHolder()), "");
                    } else {
                        r = r.replace(value.getHolder(), res.toString());
                    }
                }
            } else {
                r = r.replace(repString(r, value.getHolder()), "");
            }

        }

        for (RepeatBlock repeatBlock : repeatBlocks) {

            boolean error = false;

            boolean condition = true;

            try {
                if (repeatBlock.getCondition() != null && !(boolean) engine.eval("!!" + repeatBlock.getCondition())) {
                    condition = false;
                }
            } catch (Exception e) {
                error = true;
            }


            if (error) {
                r = r.replace(repeatBlock.getHolder(), errorText);
            } else if (condition) {

                Map m = new HashMap(allData);
                StringBuilder builder = new StringBuilder();

                String items = repeatBlock.getItems();

                if (items == null) {
                    //进行一次渲染
                    Template template = repeatBlock.getTemplate();
                    String render = template.render(m);
                    builder.append(render);
                } else {

                    //开始进行遍历操作

                    Object itemsObj = null;
                    try {
                        itemsObj = engine.eval(items);
                    } catch (Exception ignore) {
                        error = true;
                    }

                    if (error) {
                        r = r.replace(repeatBlock.getHolder(), errorText);
                    } else if (itemsObj != null) {
                        if (itemsObj instanceof Object[]) {
                            itemsObj = Arrays.asList((Object[]) itemsObj);
                        }
                        if (itemsObj instanceof Iterable) {
                            Iterable k = (Iterable) itemsObj;
                            for (Object o : k) {
                                m.put(repeatBlock.getItem(), o);
                                Template template = repeatBlock.getTemplate();
                                String render = template.render(m);
                                builder.append(render);
                            }
                        } else {
                            throw new RuntimeException("不可遍历对象:" + repeatBlock.getItems());
                        }
                    }

                }

                String s = builder.toString();

                if (s.equals("")) {
                    r = r.replace(repString(r, repeatBlock.getHolder()), "");
                } else {
                    r = r.replace(repeatBlock.getHolder(), s);
                }

            } else {
                r = r.replace(repString(r, repeatBlock.getHolder()), "");
            }

        }

        return r;
    }

    public String getText() {
        return text;
    }

    private String repString(String r, String holder) {
        int index = r.indexOf(holder);
        int pr = index - 1;
        int po = index + holder.length();

        String rep = holder;

        StringBuilder b = new StringBuilder();
        boolean pri = true;
        //开始向前查找换行符
        for (int i = pr; i >= 0; i--) {
            char c = r.charAt(i);
            if (c == ' ') {
                b.append(' ');
                continue;
            }
            if (c == '\n') {
                break;
            } else {
                pri = false;
                break;
            }
        }
        if (pri) {
            String ps = b.toString();
            b.delete(0, b.length());
            boolean poi = true;
            for (int i = po; i < r.length(); i++) {
                char c = r.charAt(i);
                if (c == ' ') {
                    b.append(' ');
                    continue;
                }
                if (c == '\n') {
                    break;
                } else {
                    poi = false;
                    break;
                }
            }

            if (poi) {
                rep = ps + rep + b.toString() + "\n";
            }

        }

        return rep;
    }


}

